#include "stdafx.h"
#include "cvxCapture.h"
#include "cvxIo.h"


CvxCapture::CvxCapture()
{
	m_step = 1;
}

CvxCapture::~CvxCapture()
{

}

/************************************************************************/
/* 
	CvxFileCapture
*/
/************************************************************************/

CvxFileCapture::CvxFileCapture(CvCapture *cp, int step)
{
	assert(cp);
	
	m_capture = cp;	
	m_step = step;
	m_size = cvSize(cvRound(cvGetCaptureProperty(cp, CV_CAP_PROP_FRAME_WIDTH)), 
				    cvRound(cvGetCaptureProperty(cp, CV_CAP_PROP_FRAME_HEIGHT)));
	m_flipMode = -2;   //not flip
	int a = cvSetCaptureProperty(m_capture, CV_CAP_PROP_POS_FRAMES , 1);

	m_currentFrame = NULL;
	m_deleteFrame = NULL;
	m_curFrameIdx  = 0; 

}
CvxFileCapture::~CvxFileCapture()
{
	if (m_currentFrame)
	{
		cvReleaseImage(&m_currentFrame);
	}
	if (m_deleteFrame)
	{
		cvReleaseImage(&m_deleteFrame);
	}	

}

// CVX_FILE_CAP_PROP_FPS     =0,
// CVX_FILE_CAP_PROP_WIDTH   =1,
// CVX_FILE_CAP_PROP_HEIGHT  =2,
// CVX_FILE_CAP_PROP_FORWARD =3  

int CvxFileCapture::SetProperty(int property_id, double value )
{
	int ret = 1;
	switch(property_id)
	{
	case CVX_FILE_CAP_PROP_WIDTH:
		m_size.width = cvRound(value);
		break;
	case CVX_FILE_CAP_PROP_HEIGHT:
		m_size.height = cvRound(value);
		break;
//	case CVX_FILE_CAP_PROP_FORWARD_FRAMRS:
//		m_currentTime += m_timeStep * cvRound(value);
//		break;
	case CVX_FILE_CAP_FLIP:
		{
			int tflip = cvRound(value);
			if (tflip != -1 && tflip != 0 && tflip != 1)
			{
				std::cout<<"CvxFileCapture::SetProperty error! This flip mode is not exist."<<endl;
				return 1;
			}
			else
			{
				m_flipMode = tflip;
			}
		}		
		break;
	default:
			std::cout<<"CvxFileCapture::SetProperty error! This property is not exist."<<endl;
			return 1;
	}
	return 0;
}
double CvxFileCapture::GetProperty(int property_id )
{
	switch(property_id)
	{
//	case CVX_FILE_CAP_PROP_FPS:
//		return 1000.0/m_timeStep;
	case CVX_FILE_CAP_PROP_WIDTH:
		return (double)m_size.width;
	case CVX_FILE_CAP_PROP_HEIGHT:
		return (double)m_size.height;
	default:
		std::cout<<"CvxFileCapture::GetProperty error! This property is not exist."<<endl;
		return 1;
	}
}

IplImage *CvxFileCapture::GetNextFrame()
{
	int step = m_step - 1;
	while(step--)
	{
		int isoK = cvGrabFrame(m_capture);
		m_curFrameIdx++;
		if (!isoK)
		{
			return NULL;
		}
	}
	IplImage *img = NULL;
	IplImage *frame = cvQueryFrame(m_capture);
	if (frame)
	{
		m_curFrameIdx++;
		if (frame->width != m_size.width || frame->height != m_size.height)
		{
			img = cvCreateImage(m_size, IPL_DEPTH_8U, 3);
			cvResize(frame, img);
		}
		else
		{
			img = cvCloneImage(frame);
		}

		if (m_flipMode != -2)
		{
			cvFlip(img, img, m_flipMode);
		}
		m_deleteFrame = m_currentFrame;
		m_currentFrame = img;
		if (m_deleteFrame)
		{
			cvReleaseImage(&m_deleteFrame);
		}
	}	
	return img;
}
IplImage *CvxFileCapture::GetIdxFrame(int idx)
{
	int delta = idx - m_curFrameIdx;
	if (delta == 0)
	{
		m_curFrameIdx = idx;
		return cvQueryFrame(m_capture);
	}
	else if (delta > 0)
	{
		IplImage *frame = NULL;
		while(delta--)
		{
			frame = cvQueryFrame(m_capture);
			if (!frame)
			{
				printf("can not get idx = %d from video", idx);
			}
		}
		m_curFrameIdx = idx;
		return cvQueryFrame(m_capture);
	}
	else if (delta < 0)
	{
		return NULL;
	}
	

}


/************************************************************************/
/*
	ImageSequenceCapture
*/
/************************************************************************/


ImageSequenceCapture::ImageSequenceCapture()
{
	m_currentIdx = 0;
}
ImageSequenceCapture::ImageSequenceCapture(const string &path, int iscolor)
{
	vector<string> fileNames;
	bool isOk = CvxIo::travel_dir(path.c_str(), fileNames);
	size_t found;
	found= path.find_last_of("/\\");
	string folder = path.substr(0, found);
	for (int i = 0; i<fileNames.size(); ++i)
	{
		string fname = folder + string("\\") + fileNames[i];
		IplImage *image = cvLoadImage(fname.c_str(), iscolor);
		assert(image);
		m_imgVec.push_back(image);
	}
	m_currentIdx = 0;
}
ImageSequenceCapture::~ImageSequenceCapture()
{

}


IplImage *ImageSequenceCapture::GetNextFrame()
{
	if (m_currentIdx < m_imgVec.size())
	{
		return m_imgVec[m_currentIdx++];
	}
	else
	{
		return NULL;
	}

}
void ImageSequenceCapture::push_back(IplImage *img)
{
	if (img)
	{
		m_imgVec.push_back(img);
	}

}

/************************************************************************/
/* 
	CvxArbitraryCapture
*/
/************************************************************************/
CvxArbitraryCapture::CvxArbitraryCapture(CvCapture *cap)
{
	assert(cap);
	m_cap = cap;
	m_maxFrames = (int)(cvGetCaptureProperty(m_cap, CV_CAP_PROP_FRAME_COUNT)) - 1;
	int isOk = cvSetCaptureProperty(m_cap, CV_CAP_PROP_POS_FRAMES, 0);
	if (!isOk)
	{
		fprintf(stderr, "CV_CAP_PROP_POS_FRAMES is not support in this version!\n");
	}
}
CvxArbitraryCapture::~CvxArbitraryCapture()
{

}

IplImage *CvxArbitraryCapture::GetNextFrame()
{
	return cvQueryFrame(m_cap);
}

IplImage *CvxArbitraryCapture::GetFrame(unsigned int frameNum)
{
	if (frameNum > m_maxFrames)
	{
		return NULL;
	}
	int isOk = cvSetCaptureProperty(m_cap, CV_CAP_PROP_POS_FRAMES, frameNum);
	if (!isOk)
	{
		return NULL;
	}
	return cvQueryFrame(m_cap);
}


